package Arduino;

import Charts.ChartScatter;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * User: Mike
 * Date: 7/28/12
 */


public class SerialTest implements SerialPortEventListener {
    private SerialPort serialPort;

    private long lastMeasurementTime = 1;
    private String lastChunk = "";

    private List temperature = new ArrayList();
    private List humidity = new ArrayList();
    private List time = new ArrayList();

    private ChartScatter plot;

    /**
     * The port we're normally going to use.
     */
    private static final String PORT_NAMES[] = {
            "/dev/tty.usbserial-A9007UX1", // Mac OS X
            "/dev/ttyUSB0", // Linux
            "COM3", // Windows
    };
    /**
     * Buffered input stream from the port
     */
    private InputStream input;
    /**
     * The output stream to the port
     */
    private OutputStream output;
    /**
     * Milliseconds to block while waiting for port open
     */
    private static final int TIME_OUT = 2000;
    /**
     * Default bits per second for COM port.
     */
    private static final int DATA_RATE = 9600;

    public void initialize() {
        CommPortIdentifier portId = null;
        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

        // iterate through, looking for the port
        while (portEnum.hasMoreElements()) {
            CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
            for (String portName : PORT_NAMES) {
                if (currPortId.getName().equals(portName)) {
                    portId = currPortId;
                    break;
                }
            }
        }

        if (portId == null) {
            System.out.println("Could not find COM port.");
            return;
        }

        try {
            // open serial port, and use class name for the appName.
            serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT);

            // set port parameters
            serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

            // open the streams
            input = serialPort.getInputStream();
            output = serialPort.getOutputStream();

            // add event listeners
            serialPort.addEventListener(this);
            serialPort.notifyOnDataAvailable(true);
        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    /**
     * This should be called when you stop using the port.
     * This will prevent port locking on platforms like Linux.
     */
    public synchronized void close() {
        if (serialPort != null) {
            serialPort.removeEventListener();
            serialPort.close();
        }
    }

    private void createChart() {
        String title = "Temperature & Humidity";
        String xAxis = "time";
        String yAxisL = "temperature";
        String yAxisR = "humidity";

        ChartScatter plot = new ChartScatter(title, title, xAxis, yAxisL, yAxisR);
    }


    void parseIncomingData() {
        boolean clearLastChunk = false;
        boolean foundBeginning = false;
        boolean foundDelim = false;
        boolean foundEnd = false;

        String end = "";
        String delim = "";
        int beggingIndex = 0;
        int delimIndex = 0;
        int endIndex = 0;

        while (endIndex < lastChunk.length() - 1) {

            while (beggingIndex < lastChunk.length() && !delim.equals("=")) {
                delim = String.valueOf(lastChunk.charAt(beggingIndex));
                beggingIndex++;
                if (delim.equals("="))
                    foundBeginning = true;
            }
            delimIndex = beggingIndex;
            endIndex = beggingIndex;
            while (delimIndex < lastChunk.length() && !delim.equals("|")) {
                delim = String.valueOf(lastChunk.charAt(delimIndex));
                delimIndex++;
                if (delim.equals("|"))
                    foundDelim = true;
            }
            while (endIndex < lastChunk.length() && !delim.equals("-")) {
                delim = String.valueOf(lastChunk.charAt(endIndex));
                endIndex++;
                if (delim.equals("-"))
                    foundEnd = true;
            }
            if (endIndex > delimIndex && delimIndex > beggingIndex && foundBeginning && foundDelim && foundEnd) {
                String tempStr = "";
                for (int i = beggingIndex; i < delimIndex - 1; i++) {
                    tempStr = tempStr + String.valueOf(lastChunk.charAt(i));
                }
                double temp = Double.valueOf(tempStr);
                String humidStr = "";
                for (int i = delimIndex; i < endIndex - 1; i++) {
                    humidStr = humidStr + String.valueOf(lastChunk.charAt(i));
                }
                double humid = Double.valueOf(humidStr);
                temperature.add(temp);
                humidity.add(humid);
                time.add(System.currentTimeMillis());
                System.out.println(System.currentTimeMillis() + " " + temp + " " + humid);
                clearLastChunk = true;
            }
            beggingIndex++;
            delimIndex++;
            endIndex++;
            foundBeginning = false;
            foundDelim = false;
            foundEnd = false;
        }
        if (clearLastChunk)
            lastChunk = "";

    }

    /**
     * Handle an event on the serial port. Read the data and print it.
     */
    public synchronized void serialEvent(SerialPortEvent oEvent) {

        if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {


                int available = input.available();
                byte chunk[] = new byte[available];
                input.read(chunk, 0, available);

                // Displayed results are codepage dependent
//                System.out.print(new String(chunk));
                lastChunk = lastChunk + new String(chunk);
//                System.out.println("*");
//                System.out.println(lastChunk);
//                System.out.println("*");

                // if more than two seconds have gone by then it's a new data point
//                if (System.currentTimeMillis() > (lastMeasurementTime + 1000 * 2)) {
//                    System.out.print(" " + new Date(System.currentTimeMillis()).toString() + " ");
//                    System.out.print(System.currentTimeMillis() + " ");
//                    lastMeasurementTime = System.currentTimeMillis();
//                    time.add(System.currentTimeMillis());
//                }
                parseIncomingData();

//                String end = "";
//                if (lastChunk.length() > 3)
//                    end = String.valueOf(lastChunk.charAt(lastChunk.length() - 3)) + String.valueOf(lastChunk.charAt(lastChunk.length() - 2)) + String.valueOf(lastChunk.charAt(lastChunk.length() - 1));
//                if (end.equals("end")) {
//                    String delim = "|";
//                    int delimIndex = 0;
//                    while (!delim.equals("|")) {
//                        delim = String.valueOf(lastChunk.charAt(delimIndex));
//                        delimIndex++;
//                    }
//                    String tempStr = "";
//                    for (int i = 5; i < delimIndex; i++) {
//                        tempStr = tempStr + String.valueOf(lastChunk.charAt(i));
//                    }
//                    double temp = Double.valueOf(tempStr);
//                    String humidStr = "";
//                    for (int i = delimIndex; i < (lastChunk.length() - 2); i++) {
//                        humidStr = humidStr + String.valueOf(lastChunk.charAt(i));
//                    }
//                    double humid = Double.valueOf(humidStr);
//                    temperature.add(temp);
//                    humidity.add(humid);
//                    time.add(System.currentTimeMillis());
//                    System.out.println(System.currentTimeMillis() + " " + temp + " " + humid);
//                    lastChunk = "";
//                }


            } catch (Exception e) {
                System.err.println(e.toString());
            }
        }

        // Ignore all the other eventTypes, but you should consider the other ones.

        if (oEvent.getEventType() == SerialPortEvent.BI) {
            System.out.println("SerialPortEvent.BI");
        }
        if (oEvent.getEventType() == SerialPortEvent.CD) {
            System.out.println("SerialPortEvent.CD");
        }
        if (oEvent.getEventType() == SerialPortEvent.CTS) {
            System.out.println("SerialPortEvent.CTS");
        }
        if (oEvent.getEventType() == SerialPortEvent.DSR) {
            System.out.println("SerialPortEvent.DSR");
        }
        if (oEvent.getEventType() == SerialPortEvent.FE) {
            System.out.println("SerialPortEvent.FE");
        }
        if (oEvent.getEventType() == SerialPortEvent.OE) {
            System.out.println("SerialPortEvent.OE");
        }
        if (oEvent.getEventType() == SerialPortEvent.PE) {
            System.out.println("SerialPortEvent.PE");
        }
        if (oEvent.getEventType() == SerialPortEvent.RI) {
            System.out.println("SerialPortEvent.RI");
        }
        if (oEvent.getEventType() == SerialPortEvent.OUTPUT_BUFFER_EMPTY) {
            System.out.println("SerialPortEvent.OUTPUT_BUFFER_EMPTY");
        }

    }


    public static void main(String[] args) throws Exception {
        SerialTest main = new SerialTest();
        main.initialize();
        System.out.println("Started");
    }
}